package com.wiscamp.ninechapters.problems.adapter.resources.exams;

import com.wiscamp.ninechapters.problems.application.dto.ExamProblemTypesDto;
import com.wiscamp.ninechapters.problems.application.dto.commands.exams.*;
import com.wiscamp.ninechapters.problems.application.dto.vo.exams.ExamTypeRelationVO;
import com.wiscamp.ninechapters.problems.application.dto.vo.exams.ExamVO;
import com.wiscamp.ninechapters.problems.application.dto.vo.exams.ScoringRuleVO;
import com.wiscamp.ninechapters.problems.application.services.ExamAppService;
import cube.ddd.adapter.BaseController;
import cube.ddd.adapter.RestResponse;
import cube.ddd.application.command.DeleteCommand;
import cube.ddd.application.command.DisableCommand;
import cube.ddd.application.command.EnableCommand;
import cube.ddd.aspect.HandleResourceException;
import cube.ddd.common.query.PagedQuery;
import cube.ddd.utils.ResourceUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.core.Context;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;

/**
 * 考试服务端点
 *
 * @author yifeng
 */
@RestController
@RequestMapping("/api/Problems")
@Tag(name = "题库-考试信息")
public class ExamController extends BaseController {
    private final ExamAppService examAppService;

    public ExamController(ExamAppService examAppService) {
        this.examAppService = examAppService;
    }

    //region exam

    /**
     * @param request
     * @param response
     * @param examId
     * @return
     */
    @GetMapping("Exams/{examId}")
    @Operation(summary = "通过考试编号获取考试")
    @HandleResourceException
    public RestResponse<ExamVO> getExam(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                        @PathVariable("examId") long examId) {
        return ResourceUtils.getById(request, response, examId, examAppService::getExam);
    }

    /**
     * 根据机构编号获取考试列表
     *
     * @param organizationId
     * @return 考试列表
     */
    @GetMapping("Organizations/{organizationId}/Exams")
    @Operation(summary = "根据机构编号获取考试列表")
    @HandleResourceException
    public RestResponse<Collection<ExamVO>> getExamsByOrganization(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                   @PathVariable("organizationId") long organizationId) {
        return ResourceUtils.getListById(request, response, organizationId, examAppService::getExamsByOrganization);
    }

    /**
     * 通过机构编号和考试代码获取考试
     *
     * @param examCode
     * @return
     */
    @GetMapping("Organizations/{organizationId}/Exams/Code/{examCode}")
    @Operation(summary = "根据机构编号和考试代码获取考试")
    @HandleResourceException
    public RestResponse<ExamVO> getExamByCode(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                              @PathVariable("organizationId") long organizationId,
                                              @PathVariable("examCode") String examCode) {
        return ResourceUtils.getByTextAndId(request, response, examCode, organizationId, examAppService::getExamByCode);
    }

    /**
     * 根据机构编号和考试名称获取考试列表
     *
     * @param examName
     * @return
     */
    @GetMapping("Organizations/{organizationId}/Exams/Name/{examName}")
    @Operation(summary = "根据机构编号和考试名称获取考试列表")
    @HandleResourceException
    public RestResponse<Collection<ExamVO>> getExamsByName(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                           @PathVariable("organizationId") long organizationId,
                                                           @PathVariable("examName") String examName) {
        return ResourceUtils.getListByTextAndId(request, response, examName, organizationId, examAppService::getExamsByName);
    }

    /**
     * 分页获取考试列表
     *
     * @return 考试列表
     */
    @PostMapping("Exams/Query")
    @Operation(summary = "分页获取考试列表")
    @HandleResourceException
    public RestResponse<Collection<ExamVO>> getExamsByQuery(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                            @RequestBody PagedQuery query) {
        return ResourceUtils.getPagedObjectsByQuery(request, response, query, examAppService::getExamsByQuery);
    }

    /**
     * 创建考试
     *
     * @param command
     * @return
     */
    @PostMapping("Exams")
    @Operation(summary = "创建考试")
    @HandleResourceException
    public RestResponse<ExamVO> createExam(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                           @RequestBody CreateExamCommand command) {
        return ResourceUtils.createOrUpdate(request, response, command, examAppService::createExam);
    }

    /**
     * 更新考试
     *
     * @param command
     * @return
     */
    @PutMapping("Exams")
    @Operation(summary = "更新考试")
    @HandleResourceException
    public RestResponse<ExamVO> updateExam(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                           @RequestBody UpdateExamCommand command) {
        return ResourceUtils.createOrUpdate(request, response, command, examAppService::updateExam);
    }

    /**
     * 通过考试编号删除考试
     *
     * @param id
     * @return
     */
    @PutMapping("Exams/Actions/Delete")
    @Operation(summary = "通过考试编号删除考试")
    @HandleResourceException
    public RestResponse<Boolean> deleteExam(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                            @RequestBody DeleteCommand command) {
        return ResourceUtils.delete(request, response, command, examAppService::deleteExam);
    }

    @DeleteMapping("Exams/{examId}")
    @Operation(summary = "通过考试编号删除考试")
    @HandleResourceException
    public RestResponse<Boolean> deleteExam2(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                             @PathVariable("examId") long examId) {
        var command = new DeleteCommand();
        command.setId(examId);
        var success = examAppService.deleteExam(command);
        return ResourceUtils.getOkResponse(request, response, success);
    }

    @PutMapping("Exams/Actions/Enable")
    @Operation(summary = "通过考试编号启用考试")
    @HandleResourceException
    public RestResponse<Boolean> enableExam(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                            @RequestBody EnableCommand command) {
        return ResourceUtils.enable(request, response, command, examAppService::enableExam);
    }

    @PutMapping("Exams/Actions/Disable")
    @Operation(summary = "通过考试编号禁用考试")
    @HandleResourceException
    public RestResponse<Boolean> disableExam(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                             @RequestBody DisableCommand command) {
        return ResourceUtils.disable(request, response, command, examAppService::disableExam);
    }

    //endregion


    //region typeRelations
    @GetMapping("Exams/{examId}/TypeRelations/{id}")
    @Operation(summary = "获取考试与题型关联")
    @HandleResourceException
    public RestResponse<ExamTypeRelationVO> getExamTypeRelation(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                @PathVariable("id") long id) {
        return ResourceUtils.getById(request, response, id, examAppService::getExamTypeRelation);
    }

    @GetMapping("Exams/{examId}/TypeRelations")
    @Operation(summary = "通过考试编号获取考试与题型关联列表")
    @HandleResourceException
    public RestResponse<Collection<ExamTypeRelationVO>> getExamTypeRelationsByExam(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                                   @PathVariable("examId") long examId) {
        return ResourceUtils.getListById(request, response, examId, examAppService::getExamTypeRelationsByExam);
    }

    /**
     * 创建考试与题型关联
     *
     * @param command
     * @return
     */
    @PostMapping("Exams/{examId}/TypeRelations")
    @Operation(summary = "创建考试与题型关联")
    @HandleResourceException
    public RestResponse<ExamTypeRelationVO> createTypeRelation(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                               @RequestBody CreateExamTypeRelationCommand command) {
        return ResourceUtils.createOrUpdate(request, response, command, examAppService::createExamTypeRelation);
    }

    @PutMapping("Exams/{examId}/TypeRelations")
    @Operation(summary = "修改考试与题型关联")
    @HandleResourceException
    public RestResponse<ExamTypeRelationVO> updateTypeRelation(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                               @RequestBody UpdateExamTypeRelationCommand command) {
        return ResourceUtils.createOrUpdate(request, response, command, examAppService::updateExamTypeRelation);
    }

    /**
     * 通过关联编号删除考试与题型关联
     *
     * @param id
     * @return
     */
    @DeleteMapping("Exams/{examId}/TypeRelations")
    @Operation(summary = "通过关联编号删除考试与题型关联")
    @HandleResourceException
    public RestResponse<Boolean> deleteTypeRelation(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                    @RequestBody DeleteCommand command) {
        return ResourceUtils.delete(request, response, command, examAppService::deleteExamTypeRelation);
    }

    @DeleteMapping("Exams/{examId}/TypeRelations/{id}")
    @Operation(summary = "通过关联编号删除考试与题型关联")
    @HandleResourceException
    public RestResponse<Boolean> deleteTypeRelationById(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                        @PathVariable("examId") long examId, @PathVariable("id") long id) {
        var command = new DeleteCommand();
        command.setId(id);
        return ResourceUtils.delete(request, response, command, examAppService::deleteExamTypeRelation);
    }


    @GetMapping("Exams/{examId}/ProblemTypes")
    @Operation(summary = "通过考试编号获取考试与题型列表")
    @HandleResourceException
    public RestResponse<ExamProblemTypesDto> getProblemTypesByExam(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                   @PathVariable("examId") long examId) {
        return ResourceUtils.getListById(request, response, examId, examAppService::getProblemTypesByExam);
    }
    //endregion


    //region scoringRules
    @GetMapping("Exams/{examId}/ScoringRules/{id}")
    @Operation(summary = "获取考试与计分规则关联")
    @HandleResourceException
    public RestResponse<ScoringRuleVO> getScoringRule(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                      @PathVariable("id") long id) {
        return ResourceUtils.getById(request, response, id, examAppService::getScoringRule);
    }

    @GetMapping("Exams/{examId}/ScoringRules")
    @Operation(summary = "通过考试编号获取考试与计分规则关联列表")
    @HandleResourceException
    public RestResponse<Collection<ScoringRuleVO>> getScoringRulesByExam(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                         @PathVariable("examId") long examId) {
        return ResourceUtils.getListById(request, response, examId, examAppService::getScoringRulesByExam);
    }

    /**
     * 创建考试与计分规则关联
     *
     * @param command
     * @return
     */
    @PostMapping("Exams/{examId}/ScoringRules")
    @Operation(summary = "创建考试与计分规则关联")
    @HandleResourceException
    public RestResponse<ScoringRuleVO> createScoringRule(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                         @RequestBody CreateScoringRuleCommand command) {
        return ResourceUtils.createOrUpdate(request, response, command, examAppService::createScoringRule);
    }

    @PutMapping("Exams/{examId}/ScoringRules")
    @Operation(summary = "修改考试与计分规则关联")
    @HandleResourceException
    public RestResponse<ScoringRuleVO> updateScoringRule(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                         @RequestBody UpdateScoringRuleCommand command) {
        return ResourceUtils.createOrUpdate(request, response, command, examAppService::updateScoringRule);
    }

    /**
     * 通过关联编号删除考试与计分规则关联
     *
     * @param id
     * @return
     */
    @DeleteMapping("Exams/{examId}/ScoringRules")
    @Operation(summary = "通过关联编号删除考试与计分规则关联")
    @HandleResourceException
    public RestResponse<Boolean> deleteScoringRule(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                   @RequestBody DeleteCommand command) {
        return ResourceUtils.delete(request, response, command, examAppService::deleteScoringRule);
    }

    //endregion
}
